/**
 * \file KernelSymbols.cc
 * \brief Kernel symbol table and symbol lookup.
 * \author Corey Tabaka
 */

/*
   Copyright 2005 Corey Tabaka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "ktypes.h"
#include "KernelSymbols.h"
#include <stdio.h>
#include <string.h>

#define EXTERN(sym) extern byte sym[]
#define SECTION(base, sym) { "."#base"$"#sym, 0 }
#define SYMBOL(sym) { ""#sym, (void *) sym }
#define OBJECT(sym) { ""#sym, &sym }

EXTERN(code);
EXTERN(_code);

// udivmoddi3.o -- gcc 64-bit mod and div
EXTERN(__udivdi3);
EXTERN(__umoddi3);

// MemoryCpp.o -- new/delete
EXTERN(_ZdlPv);
EXTERN(_ZdaPv);
EXTERN(_Znwj);
EXTERN(_Znaj);
EXTERN(_ZnajPvj);

// virtual function support cxa_abi.o
EXTERN(__cxa_pure_virtual);

// lzss.o
EXTERN(decompress_lzss);

// spinlock.o
EXTERN(interrupt_mutex_wait);
EXTERN(interrupt_mutex_init);
EXTERN(spinlock_try);
EXTERN(spinlock_signal);
EXTERN(spinlock_init);
EXTERN(spinlock_wait);
EXTERN(interrupt_mutex_signal);

// mutex.o
EXTERN(mutex_wait);
EXTERN(mutex_init);
EXTERN(semaphore_signal);
EXTERN(semaphore_init);
EXTERN(semaphore_wait);
EXTERN(mutex_try);
EXTERN(mutex_signal);

// syscall.o
EXTERN(syscall32);
EXTERN(syscall);
EXTERN(syscall64);

// cprintf.o
EXTERN(cprintf);
EXTERN(printf_xy);
//EXTERN(printf);

// malloc.o
EXTERN(free);
EXTERN(mallopt);
EXTERN(malloc_usable_size);
EXTERN(mallinfo);
EXTERN(malloc_stats);
EXTERN(independent_calloc);
EXTERN(calloc);
EXTERN(pvalloc);
EXTERN(cfree);
EXTERN(realloc);
EXTERN(memalign);
EXTERN(malloc);
EXTERN(independent_comalloc);
EXTERN(valloc);
EXTERN(malloc_trim);

// panic.o
EXTERN(panic);
EXTERN(abort);
EXTERN(trace);

// atomic.o
EXTERN(atomic_exchange);
EXTERN(atomic_set);
EXTERN(atomic_add);
EXTERN(atomic_and);
EXTERN(atomic_or);

// klibc:cons.o
EXTERN(putc_xy);
EXTERN(_scroll);
EXTERN(bios_restore);
EXTERN(bios_save);
EXTERN(puts_xy);
EXTERN(_clear);
EXTERN(cputs);
EXTERN(scroll);
EXTERN(get_visual_page);
EXTERN(cputc);
EXTERN(window);
EXTERN(set_visual_page);
EXTERN(set_active_page);
EXTERN(getc_xy);
EXTERN(place);
EXTERN(get_active_page);
EXTERN(cursor);
EXTERN(clear);

#if 0
// klibc:string.o
EXTERN(strcat);
EXTERN(strcmp);
EXTERN(strupr);
EXTERN(strlwr);
EXTERN(strncpy);
EXTERN(strdup);
EXTERN(strcasecmp);
//EXTERN(strpbrk);
EXTERN(strchr);
EXTERN(strcpy);
EXTERN(strncmp);
EXTERN(strscn);
EXTERN(strsep);
EXTERN(strlen);
EXTERN(strstr);

// klibc:strtoi.o
EXTERN(strtoi);

// klibc:strtou.o
EXTERN(strtou);

// klibc:ucvt.o
EXTERN(ucvt);
EXTERN(dcvt);

// klibc:sprintf.o
EXTERN(sprintf);
EXTERN(vsprintf);
#endif

// klibc:strbase.o
EXTERN(tonumber);
EXTERN(isnumber);
EXTERN(todigit);

// Log.o
EXTERN(_ZN3Log7hexdumpEiPKhjb);
EXTERN(_ZN3Log8getLevelEv);
EXTERN(_ZN3Log6printfEiPKcz);
EXTERN(_ZN3Log10setConsoleEPFvPKcE);
EXTERN(_ZN3Log8setLevelEi);
//EXTERN(_ZN3Log10initializeEv);

// Namespace.o
EXTERN(_ZN3VarC1EPKcS1_i);
EXTERN(_ZN9Namespace6getIntEPKc);
EXTERN(_ZN9Namespace13unregisterVarER3Var);
EXTERN(_ZN3Var3setEx);
EXTERN(_ZN3VaraSEx);
EXTERN(_ZN3Var3setEPKc);
EXTERN(_ZN3VarC2EPKcxi);
EXTERN(_ZN9Namespace6createEPKcS1_i);
EXTERN(_ZN3VarD2Ev);
//EXTERN(_ZN9Namespace10initializeEv);
EXTERN(_ZN9Namespace5isKeyEPKc);
EXTERN(_ZN3VarC2EPKcS1_i);
EXTERN(_ZN3VarD1Ev);
EXTERN(_ZN3VaraSEPKc);
EXTERN(_ZN9Namespace3setEPKcS1_);
EXTERN(_ZN9Namespace6createEPKcxi);
EXTERN(_ZN3Var11setListenerEP11VarListener);
EXTERN(_ZN9Namespace3setEPKcx);
EXTERN(_ZN9Namespace9getStringEPKc);
EXTERN(_ZN9Namespace8dumpVarsEPKc);
EXTERN(_ZN9Namespace11registerVarER3Var);
EXTERN(_ZN3VarC1EPKcxi);

// Memory.o
//EXTERN(_ZN6Memory10initializeEv);
EXTERN(_ZN6Memory18getPhysicalPageMapEv);
EXTERN(_ZN6Memory5allocEj);
EXTERN(_ZN6Memory4freeEPvj);

// Interrupt.o
EXTERN(_ZN9Interrupt22disableLocalInterruptsEv);
EXTERN(_ZN9Interrupt4maskEh);
EXTERN(_ZN9Interrupt17unregisterHandlerEhPFbP6regs_tE);
EXTERN(_ZN9Interrupt6unmaskEh);
EXTERN(_ZN9Interrupt9isHandledEh);
//EXTERN(_ZN9Interrupt10initializeEv);
EXTERN(interrupt_handler);
EXTERN(_ZN9Interrupt15registerHandlerEhPFbP6regs_tEi);
EXTERN(_ZN9Interrupt16waitForInterruptEv);
EXTERN(_ZN9Interrupt21enableLocalInterruptsEv);

// Pic.o
EXTERN(_ZN3Pic7isOwnedEh);
EXTERN(_ZN3Pic14disableAllIRQsEv);
EXTERN(_ZN3Pic6enableEhb);
//EXTERN(_ZN3Pic10initializeEv);
EXTERN(_ZN3Pic8issueEOIEh);
EXTERN(_ZN3Pic7isLevelEh);
EXTERN(_ZN3Pic9isPendingEh);

// Timer.o
EXTERN(_ZN5Timer12getFrequencyEv);
EXTERN(_ZN5Timer17getCpuTicksPerSecEv);
EXTERN(_ZN5Timer9getMillisEv);
EXTERN(_ZN5Timer15calibrateTimersEv);
EXTERN(_ZN5Timer18getCpuTicksPerNanoEv);
EXTERN(_ZN5Timer19getCpuTicksPerMicroEv);
EXTERN(_ZN5Timer12getMicroTimeEv);
EXTERN(_ZN5Timer8getTicksEv);
//EXTERN(_ZN5Timer10initializeEv);

// Pci.o
EXTERN(_ZN3Pci10readConfigER14pci_location_tjPh);
//EXTERN(_ZN3Pci10initializeEv);
EXTERN(_ZN3Pci12readConfig32ER14pci_location_tjPj);
EXTERN(_ZN3Pci11writeConfigER14pci_location_tjh);
EXTERN(_ZN3Pci13writeConfig16ER14pci_location_tjt);
EXTERN(_ZN3Pci12readConfig16ER14pci_location_tjPt);
EXTERN(_ZN3Pci10findDeviceER14pci_location_tttt);
EXTERN(_ZN3Pci20getIrqRoutingOptionsEP17irq_routing_entryRtS2_);
EXTERN(_ZN3Pci11setIrqHwIntER14pci_location_thh);
EXTERN(_ZN3Pci13writeConfig32ER14pci_location_tjj);
EXTERN(_ZN3Pci13findClassCodeER14pci_location_tjt);

// PageMap.o
EXTERN(_ZN7PageMapC2Ev);
EXTERN(_ZN7PageMap4freeEjj);
EXTERN(_ZN7PageMapD1Ev);
EXTERN(_ZN7PageMapD2Ev);
EXTERN(_ZN7PageMap12getFreePagesEv);
EXTERN(_ZN7PageMap5allocEPjj);
EXTERN(_ZN7PageMap4dumpEv);
EXTERN(_ZN7PageMapC1Ev);
EXTERN(_ZN7PageMap5allocEPj);
EXTERN(_ZN7PageMapC2Ejj);
EXTERN(_ZN7PageMap6isFreeEj);
EXTERN(_ZN7PageMap4freeEj);
EXTERN(_ZN7PageMap7reserveEjj);
EXTERN(_ZN7PageMap17getAllocatedPagesEv);
EXTERN(_ZN7PageMap13getFreedPagesEv);
EXTERN(_ZN7PageMap7reserveEj);
EXTERN(_ZN7PageMapC1Ejj);
EXTERN(_ZN7PageMap12getPeakPagesEv);
EXTERN(_ZN7PageMap10initializeEjj);

// PageTable.o
EXTERN(_ZN9PageTable9isCurrentEv);
EXTERN(_ZN9PageTable11makeCurrentEv);
EXTERN(_ZN9PageTable4copyEPKS_);
EXTERN(_ZN9PageTableC2Ev);
EXTERN(_ZN9PageTableD1Ev);
EXTERN(_ZN9PageTable21physicalFromEffectiveEPvPb);
EXTERN(_ZN9PageTable7acquireEPvS0_jbj);
EXTERN(_ZN9PageTable7releaseEPvj);
EXTERN(_ZN9PageTableC1Ev);
EXTERN(_ZN9PageTableD2Ev);

// Process.o
EXTERN(_ZN7ProcessC2EPKc);
EXTERN(_ZN7Process13createProcessEPKc);
EXTERN(_ZN7ProcessD2Ev);
EXTERN(_ZN7Process12getPageTableEv);
EXTERN(_ZN7Process11destroyPipeEj);
EXTERN(_ZN7Process10loadBinaryEPKvjjb);
EXTERN(_ZN7ProcessD0Ev);
EXTERN(_ZN7Process12loadPeModuleEPKvjb);
EXTERN(_ZN7Process16getSystemProcessEv);
EXTERN(_ZN7Process9loadPeExeEPKvjb);
EXTERN(_ZN7Process7getPipeEj);
//EXTERN(_ZN7Process10initializeEv);
EXTERN(_ZN7Process10getPageMapEv);
EXTERN(_ZN7Process17getCurrentProcessEv);
EXTERN(_ZN7ProcessC1EPKc);
EXTERN(_ZN7Process7getNameEv);
EXTERN(_ZN7ProcessD1Ev);
EXTERN(_ZN7Process10getProcessEj);
EXTERN(_ZN7Process10createPipeEv);
EXTERN(_ZN7Process15getAddressSpaceEv);
EXTERN(_ZN7ProcessC1EPKcR7PageMap);
EXTERN(_ZN7ProcessC2EPKcR7PageMap);

EXTERN(_ZN8RefCountI7ProcessED1Ev);
EXTERN(_ZNK8RefCountI6ThreadEptEv);
EXTERN(_ZN8RefCountI6ThreadED1Ev);

// Thread.o
EXTERN(_ZN6Thread5yieldEv);
EXTERN(_ZN6Thread11tickHandlerEP6regs_t);
EXTERN(_ZN6Thread4saveEP6regs_t);
//EXTERN(_ZN6Thread10initializeEv);
EXTERN(_ZN10UserThreadD0Ev);
EXTERN(_ZN6Thread10getProcessEv);
EXTERN(_ZN10VM86ThreadD2Ev);
EXTERN(_ZN10UserThread9growStackEv);
EXTERN(_ZN6Thread4waitEv);
EXTERN(_ZN10VM86Thread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN6Thread12queuePrependEPS_i);
EXTERN(_ZN6Thread11queueRemoveEPS_i);
EXTERN(_ZN10VM86ThreadC1EPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN10UserThread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN6Thread4idleEPv);
EXTERN(_ZN6Thread19getFloatingPriorityEv);
EXTERN(_ZN6Thread5sleepEj);
EXTERN(_ZN6Thread8getErrnoEv);
EXTERN(_ZN10UserThreadC2EPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN10UserThread11shrinkStackEv);
EXTERN(_ZN10UserThreadD2Ev);
EXTERN(_ZN6Thread6notifyEv);
EXTERN(_ZN10UserThreadD1Ev);
EXTERN(_ZN6Thread11queueAppendEPS_i);
EXTERN(_ZN6Thread19setFloatingPriorityEi);
EXTERN(_ZN10VM86ThreadD0Ev);
EXTERN(_ZN6Thread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN10UserThreadC1EPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN6Thread5beginEv);
EXTERN(_ZN6ThreadD2Ev);
EXTERN(_ZN6Thread14syscallHandlerEP6regs_t);
EXTERN(_ZN6Thread12faultHandlerEP6regs_t);
EXTERN(_ZN6Thread6getTidEv);
EXTERN(_ZN6Thread16getCurrentThreadEv);
EXTERN(_ZN10VM86Thread5faultEP6regs_t);
EXTERN(_ZN6Thread7getNameEv);
EXTERN(_ZN6ThreadC1EPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN6ThreadD0Ev);
EXTERN(_ZN6Thread10rescheduleEP6regs_t);
EXTERN(_ZN6Thread5faultEP6regs_t);
EXTERN(_ZN6Thread11setPriorityEi);
EXTERN(_ZN6ThreadC2E13thread_type_t);
EXTERN(_ZN6Thread4killEv);
EXTERN(_ZN10VM86ThreadC2EPFvPvES0_PKc8RefCountI7ProcessE);
EXTERN(_ZN6ThreadC1E13thread_type_t);
EXTERN(_ZN6ThreadD1Ev);
EXTERN(_ZN10VM86ThreadD1Ev);
EXTERN(_ZN10VM86Thread18emulateInstructionEP11regs_vm86_t);
EXTERN(_ZN6Thread3runEv);
EXTERN(_ZN6Thread11getPriorityEv);
EXTERN(_ZN6Thread7restoreEP6regs_t);
EXTERN(_ZN6Thread13switchThreadsEv);
EXTERN(_ZN10UserThread11adjustStackEP6regs_t);
EXTERN(_ZN6ThreadC2EPFvPvES0_PKc8RefCountI7ProcessE);


// Queue.o
EXTERN(_ZN5QueueC2Ev);
EXTERN(_ZN5Queue6removeEP9QueueNode);
EXTERN(_ZN5Queue7prependEP9QueueNode);
EXTERN(_ZN5Queue10initializeEv);
EXTERN(_ZN5QueueD1Ev);
EXTERN(_ZN5Queue6insertEP9QueueNode);
EXTERN(_ZN5Queue7getHeadEv);
EXTERN(_ZN5QueueC1Ev);
EXTERN(_ZN5QueueD2Ev);
EXTERN(_ZN5Queue6appendEP9QueueNode);
EXTERN(_ZN5Queue8getCountEv);

EXTERN(_ZN5QList10removeTailEv);
EXTERN(_ZN5QListC2Ev);
EXTERN(_ZN5QList6removeEv);
EXTERN(_ZN5QList10removeHeadEv);
EXTERN(_ZN5QList7prependEPS_);
EXTERN(_ZN5QList4tailEv);
EXTERN(_ZN5QList7getNextEPS_);
EXTERN(_ZN5QListC1Ev);
EXTERN(_ZN5QList6appendEPS_);
EXTERN(_ZN5QList4headEv);
EXTERN(_ZN5QList5clearEv);
EXTERN(_ZN5QList7isEmptyEv);


// Message.o
EXTERN(_ZN11MessagePipeD1Ev);
EXTERN(_ZN13MessageBuffer4readEPhj);
EXTERN(_ZN13MessageBufferC2Ej);
EXTERN(_ZN11MessagePipe5replyEPKvj);
EXTERN(_ZN11MessagePipe4sendEPKvjS1_jPvjS2_j);
EXTERN(_ZN13MessageBuffer4readEPhjS0_j);
EXTERN(_ZN13MessageBuffer5writeEPKhj);
EXTERN(_ZN11MessagePipe5replyEPKvjS1_j);
EXTERN(_ZN11MessagePipe4sendEPKvjPvj);
EXTERN(_ZN13MessageBufferD2Ev);
EXTERN(_ZN11MessagePipeC1Ev);
EXTERN(_ZN11MessagePipeD2Ev);
EXTERN(_ZN11MessagePipeD0Ev);
EXTERN(_ZN13MessageBuffer11checkBufferEj);
EXTERN(_ZN11MessagePipe7receiveEPvjS0_j);
EXTERN(_ZN11MessagePipe10invalidateEv);
EXTERN(_ZN13MessageBufferC1Ej);
EXTERN(_ZN13MessageBuffer5writeEPKhjS1_j);
EXTERN(_ZN11MessagePipe7isValidEv);
EXTERN(_ZN11MessagePipeC2Ev);
EXTERN(_ZN11MessagePipe7receiveEPvj);
EXTERN(_ZN13MessageBufferD1Ev);

// AddressSpace.o
EXTERN(_ZN6RegionD2Ev);
EXTERN(_ZN12AddressSpace5firstEv);
EXTERN(_ZN12AddressSpaceC2Ev);
EXTERN(_ZN12AddressSpaceD1Ev);
EXTERN(_ZN12AddressSpace4lastEv);
EXTERN(_ZN6Region7getTypeEv);
EXTERN(_ZN12AddressSpaceC2EP9PageTableP7PageMap);
EXTERN(_ZN12AddressSpace6removeEP6Region);
EXTERN(_ZN12AddressSpaceD2Ev);
EXTERN(_ZN6Region7getSizeEv);
EXTERN(_ZN12AddressSpace11findVirtualEj);
EXTERN(_ZN6Region14getVirtualBaseEv);
EXTERN(_ZN12AddressSpaceC1EP9PageTableP7PageMap);
EXTERN(_ZN12AddressSpace8findTypeEj);
EXTERN(_ZN12AddressSpace7destroyEP6Region);
EXTERN(_ZN6RegionC1EP12AddressSpacejjjjj);
EXTERN(_ZN6Region7getNextEj);
EXTERN(_ZN6Region8getFlagsEv);
EXTERN(_ZN6RegionD1Ev);
EXTERN(_ZN12AddressSpace12findPhysicalEj);
EXTERN(_ZN12AddressSpaceC1Ev);
EXTERN(_ZN12AddressSpace6createEjjjjj);
EXTERN(_ZN12AddressSpace6insertEP6Region);
EXTERN(_ZN6Region15getPhysicalBaseEv);
EXTERN(_ZN6RegionC2EP12AddressSpacejjjjj);

static struct {
	const char *name;
	const void * adr;
} syms[] = {
	SYMBOL(code),
	SYMBOL(_code),

	// console output
	SYMBOL(printf),
	SYMBOL(printf_xy),

	// synchronization
	SYMBOL(spinlock_init),
	SYMBOL(spinlock_wait),
	SYMBOL(spinlock_try),
	SYMBOL(spinlock_signal),
	SYMBOL(interrupt_mutex_init),
	SYMBOL(interrupt_mutex_wait),
	SYMBOL(interrupt_mutex_signal),
	SYMBOL(mutex_init),
	SYMBOL(mutex_wait),
	SYMBOL( mutex_try),
	SYMBOL(mutex_signal),
	SYMBOL(semaphore_init),
	SYMBOL(semaphore_wait),
	SYMBOL(semaphore_signal),

	// malloc
	SYMBOL(free),
	SYMBOL(mallopt),
	SYMBOL(malloc_usable_size),
	SYMBOL(mallinfo),
	SYMBOL(malloc_stats),
	SYMBOL(independent_calloc),
	SYMBOL(calloc),
	SYMBOL(pvalloc),
	SYMBOL(cfree),
	SYMBOL(realloc),
	SYMBOL(memalign),
	SYMBOL(malloc),
	SYMBOL(independent_comalloc),
	SYMBOL(valloc),
	SYMBOL(malloc_trim),

	// syscall
	SYMBOL(syscall),
	SYMBOL(syscall32),
	SYMBOL(syscall64),

	// gcc 64 bit div/mod
	SYMBOL(__umoddi3),
	SYMBOL(__udivdi3),

	// kernel panic
	SYMBOL(panic),
	SYMBOL(abort),
	SYMBOL(trace),

	// atomic
	SYMBOL(atomic_exchange),
	SYMBOL(atomic_set),
	SYMBOL(atomic_add),
	SYMBOL(atomic_and),
	SYMBOL(atomic_or),

	// string
	SYMBOL(strcpy),
	SYMBOL(strncpy),
	SYMBOL(strcmp),
	SYMBOL(strncmp),
	SYMBOL(strlen),
	SYMBOL(strscn),
	SYMBOL(strchr),
	SYMBOL(strupr),
	SYMBOL(strlwr),
	SYMBOL(strcat),
	SYMBOL(strncat),
	SYMBOL(strdup),
	SYMBOL(strcasecmp),
	SYMBOL(strstr),

	// new/delete
	SYMBOL(_ZdlPv),
	SYMBOL(_ZdaPv),
	SYMBOL(_Znwj),
	SYMBOL(_Znaj),
	SYMBOL(_ZnajPvj),

	// cxa_abi
	SYMBOL(__cxa_pure_virtual),

	// lzss
	SYMBOL(decompress_lzss),

	// klibc:cons
	SYMBOL(putc_xy),
	SYMBOL(_scroll),
	SYMBOL(bios_restore),
	SYMBOL(bios_save),
	SYMBOL(puts_xy),
	SYMBOL(_clear),
	SYMBOL(cputs),
	SYMBOL(scroll),
	SYMBOL(get_visual_page),
	SYMBOL(cputc),
	SYMBOL(window),
	SYMBOL(set_visual_page),
	SYMBOL(set_active_page),
	SYMBOL(getc_xy),
	SYMBOL(place),
	SYMBOL(get_active_page),
	SYMBOL(cursor),
	SYMBOL(clear),

	// klibc:string
	SYMBOL(strcat),
	SYMBOL(strcmp),
	SYMBOL(strupr),
	SYMBOL(strlwr),
	SYMBOL(strncpy),
	SYMBOL(strdup),
	SYMBOL(strcasecmp),
	//SYMBOL(strpbrk),
	SYMBOL(strchr),
	SYMBOL(strcpy),
	SYMBOL(strncmp),
	SYMBOL(strscn),
	SYMBOL(strsep),
	SYMBOL(strlen),
	SYMBOL(strstr),

	// klibc:strtoi
	SYMBOL(strtoi),

	// klibc:strtou
	SYMBOL(strtou),

	// klibc:ucvt
	SYMBOL(ucvt),
	SYMBOL(dcvt),

	// klibc:sprintf
	SYMBOL(sprintf),
	SYMBOL(vsprintf),

	// klibc:strbase
	SYMBOL(tonumber),
	SYMBOL(isnumber),
	SYMBOL(todigit),

	// Log.o
	SYMBOL(_ZN3Log7hexdumpEiPKhjb),
	SYMBOL(_ZN3Log8getLevelEv),
	SYMBOL(_ZN3Log6printfEiPKcz),
	SYMBOL(_ZN3Log10setConsoleEPFvPKcE),
	SYMBOL(_ZN3Log8setLevelEi),
	//SYMBOL(_ZN3Log10initializeEv),

	// Namespace.o
	SYMBOL(_ZN3VarC1EPKcS1_i),
	SYMBOL(_ZN9Namespace6getIntEPKc),
	SYMBOL(_ZN9Namespace13unregisterVarER3Var),
	SYMBOL(_ZN3Var3setEx),
	SYMBOL(_ZN3VaraSEx),
	SYMBOL(_ZN3Var3setEPKc),
	SYMBOL(_ZN3VarC2EPKcxi),
	SYMBOL(_ZN9Namespace6createEPKcS1_i),
	SYMBOL(_ZN3VarD2Ev),
	//SYMBOL(_ZN9Namespace10initializeEv),
	SYMBOL(_ZN9Namespace5isKeyEPKc),
	SYMBOL(_ZN3VarC2EPKcS1_i),
	SYMBOL(_ZN3VarD1Ev),
	SYMBOL(_ZN3VaraSEPKc),
	SYMBOL(_ZN9Namespace3setEPKcS1_),
	SYMBOL(_ZN9Namespace6createEPKcxi),
	SYMBOL(_ZN3Var11setListenerEP11VarListener),
	SYMBOL(_ZN9Namespace3setEPKcx),
	SYMBOL(_ZN9Namespace9getStringEPKc),
	SYMBOL(_ZN9Namespace8dumpVarsEPKc),
	SYMBOL(_ZN9Namespace11registerVarER3Var),
	SYMBOL(_ZN3VarC1EPKcxi),

	// Memory.o
	//SYMBOL(_ZN6Memory10initializeEv),
	SYMBOL(_ZN6Memory18getPhysicalPageMapEv),
	SYMBOL(_ZN6Memory5allocEj),
	SYMBOL(_ZN6Memory4freeEPvj),

	// Interrupt.o
	SYMBOL(_ZN9Interrupt22disableLocalInterruptsEv),
	SYMBOL(_ZN9Interrupt4maskEh),
	SYMBOL(_ZN9Interrupt17unregisterHandlerEhPFbP6regs_tE),
	SYMBOL(_ZN9Interrupt6unmaskEh),
	SYMBOL(_ZN9Interrupt9isHandledEh),
	//SYMBOL(_ZN9Interrupt10initializeEv),
	SYMBOL(interrupt_handler),
	SYMBOL(_ZN9Interrupt15registerHandlerEhPFbP6regs_tEi),
	SYMBOL(_ZN9Interrupt16waitForInterruptEv),
	SYMBOL(_ZN9Interrupt21enableLocalInterruptsEv),

	// Pic.o
	SYMBOL(_ZN3Pic7isOwnedEh),
	SYMBOL(_ZN3Pic14disableAllIRQsEv),
	SYMBOL(_ZN3Pic6enableEhb),
	//SYMBOL(_ZN3Pic10initializeEv),
	SYMBOL(_ZN3Pic8issueEOIEh),
	SYMBOL(_ZN3Pic7isLevelEh),
	SYMBOL(_ZN3Pic9isPendingEh),

	// Timer.o
	SYMBOL(_ZN5Timer12getFrequencyEv),
	SYMBOL(_ZN5Timer17getCpuTicksPerSecEv),
	SYMBOL(_ZN5Timer9getMillisEv),
	SYMBOL(_ZN5Timer15calibrateTimersEv),
	SYMBOL(_ZN5Timer18getCpuTicksPerNanoEv),
	SYMBOL(_ZN5Timer19getCpuTicksPerMicroEv),
	SYMBOL(_ZN5Timer12getMicroTimeEv),
	SYMBOL(_ZN5Timer8getTicksEv),
	//SYMBOL(_ZN5Timer10initializeEv),

	// Pci.o
	SYMBOL(_ZN3Pci10readConfigER14pci_location_tjPh),
	//SYMBOL(_ZN3Pci10initializeEv),
	SYMBOL(_ZN3Pci12readConfig32ER14pci_location_tjPj),
	SYMBOL(_ZN3Pci11writeConfigER14pci_location_tjh),
	SYMBOL(_ZN3Pci13writeConfig16ER14pci_location_tjt),
	SYMBOL(_ZN3Pci12readConfig16ER14pci_location_tjPt),
	SYMBOL(_ZN3Pci10findDeviceER14pci_location_tttt),
	SYMBOL(_ZN3Pci20getIrqRoutingOptionsEP17irq_routing_entryRtS2_),
	SYMBOL(_ZN3Pci11setIrqHwIntER14pci_location_thh),
	SYMBOL(_ZN3Pci13writeConfig32ER14pci_location_tjj),
	SYMBOL(_ZN3Pci13findClassCodeER14pci_location_tjt),

	// PageMap.o
	SYMBOL(_ZN7PageMapC2Ev),
	SYMBOL(_ZN7PageMap4freeEjj),
	SYMBOL(_ZN7PageMapD1Ev),
	SYMBOL(_ZN7PageMapD2Ev),
	SYMBOL(_ZN7PageMap12getFreePagesEv),
	SYMBOL(_ZN7PageMap5allocEPjj),
	SYMBOL(_ZN7PageMap4dumpEv),
	SYMBOL(_ZN7PageMapC1Ev),
	SYMBOL(_ZN7PageMap5allocEPj),
	SYMBOL(_ZN7PageMapC2Ejj),
	SYMBOL(_ZN7PageMap6isFreeEj),
	SYMBOL(_ZN7PageMap4freeEj),
	SYMBOL(_ZN7PageMap7reserveEjj),
	SYMBOL(_ZN7PageMap17getAllocatedPagesEv),
	SYMBOL(_ZN7PageMap13getFreedPagesEv),
	SYMBOL(_ZN7PageMap7reserveEj),
	SYMBOL(_ZN7PageMapC1Ejj),
	SYMBOL(_ZN7PageMap12getPeakPagesEv),
	SYMBOL(_ZN7PageMap10initializeEjj),

	// PageTable.o
	SYMBOL(_ZN9PageTable9isCurrentEv),
	SYMBOL(_ZN9PageTable11makeCurrentEv),
	SYMBOL(_ZN9PageTable4copyEPKS_),
	SYMBOL(_ZN9PageTableC2Ev),
	SYMBOL(_ZN9PageTableD1Ev),
	SYMBOL(_ZN9PageTable21physicalFromEffectiveEPvPb),
	SYMBOL(_ZN9PageTable7acquireEPvS0_jbj),
	SYMBOL(_ZN9PageTable7releaseEPvj),
	SYMBOL(_ZN9PageTableC1Ev),
	SYMBOL(_ZN9PageTableD2Ev),

	// Process.o
	SYMBOL(_ZN7ProcessC2EPKc),
	SYMBOL(_ZN7Process13createProcessEPKc),
	SYMBOL(_ZN7ProcessD2Ev),
	SYMBOL(_ZN7Process12getPageTableEv),
	SYMBOL(_ZN7Process11destroyPipeEj),
	SYMBOL(_ZN7Process10loadBinaryEPKvjjb),
	SYMBOL(_ZN7ProcessD0Ev),
	SYMBOL(_ZN7Process12loadPeModuleEPKvjb),
	SYMBOL(_ZN7Process16getSystemProcessEv),
	SYMBOL(_ZN7Process9loadPeExeEPKvjb),
	SYMBOL(_ZN7Process7getPipeEj),
	//SYMBOL(_ZN7Process10initializeEv),
	SYMBOL(_ZN7Process10getPageMapEv),
	SYMBOL(_ZN7Process17getCurrentProcessEv),
	SYMBOL(_ZN7ProcessC1EPKc),
	SYMBOL(_ZN7Process7getNameEv),
	SYMBOL(_ZN7ProcessD1Ev),
	SYMBOL(_ZN7Process10getProcessEj),
	SYMBOL(_ZN7Process10createPipeEv),
	SYMBOL(_ZN7Process15getAddressSpaceEv),
	SYMBOL(_ZN7ProcessC1EPKcR7PageMap),
	SYMBOL(_ZN7ProcessC2EPKcR7PageMap),

	SYMBOL(_ZN8RefCountI7ProcessED1Ev),
	SYMBOL(_ZNK8RefCountI6ThreadEptEv),
	SYMBOL(_ZN8RefCountI6ThreadED1Ev),

	// Thread.o
	SYMBOL(_ZN6Thread5yieldEv),
	SYMBOL(_ZN6Thread11tickHandlerEP6regs_t),
	SYMBOL(_ZN6Thread4saveEP6regs_t),
	//SYMBOL(_ZN6Thread10initializeEv),
	SYMBOL(_ZN10UserThreadD0Ev),
	SYMBOL(_ZN6Thread10getProcessEv),
	SYMBOL(_ZN10VM86ThreadD2Ev),
	SYMBOL(_ZN10UserThread9growStackEv),
	SYMBOL(_ZN6Thread4waitEv),
	SYMBOL(_ZN10VM86Thread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN6Thread12queuePrependEPS_i),
	SYMBOL(_ZN6Thread11queueRemoveEPS_i),
	SYMBOL(_ZN10VM86ThreadC1EPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN10UserThread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN6Thread4idleEPv),
	SYMBOL(_ZN6Thread19getFloatingPriorityEv),
	SYMBOL(_ZN6Thread5sleepEj),
	SYMBOL(_ZN6Thread8getErrnoEv),
	SYMBOL(_ZN10UserThreadC2EPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN10UserThread11shrinkStackEv),
	SYMBOL(_ZN10UserThreadD2Ev),
	SYMBOL(_ZN6Thread6notifyEv),
	SYMBOL(_ZN10UserThreadD1Ev),
	SYMBOL(_ZN6Thread11queueAppendEPS_i),
	SYMBOL(_ZN6Thread19setFloatingPriorityEi),
	SYMBOL(_ZN10VM86ThreadD0Ev),
	SYMBOL(_ZN6Thread12createThreadEPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN10UserThreadC1EPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN6Thread5beginEv),
	SYMBOL(_ZN6ThreadD2Ev),
	SYMBOL(_ZN6Thread14syscallHandlerEP6regs_t),
	SYMBOL(_ZN6Thread12faultHandlerEP6regs_t),
	SYMBOL(_ZN6Thread6getTidEv),
	SYMBOL(_ZN6Thread16getCurrentThreadEv),
	SYMBOL(_ZN10VM86Thread5faultEP6regs_t),
	SYMBOL(_ZN6Thread7getNameEv),
	SYMBOL(_ZN6ThreadC1EPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN6ThreadD0Ev),
	SYMBOL(_ZN6Thread10rescheduleEP6regs_t),
	SYMBOL(_ZN6Thread5faultEP6regs_t),
	SYMBOL(_ZN6Thread11setPriorityEi),
	SYMBOL(_ZN6ThreadC2E13thread_type_t),
	SYMBOL(_ZN6Thread4killEv),
	SYMBOL(_ZN10VM86ThreadC2EPFvPvES0_PKc8RefCountI7ProcessE),
	SYMBOL(_ZN6ThreadC1E13thread_type_t),
	SYMBOL(_ZN6ThreadD1Ev),
	SYMBOL(_ZN10VM86ThreadD1Ev),
	SYMBOL(_ZN10VM86Thread18emulateInstructionEP11regs_vm86_t),
	SYMBOL(_ZN6Thread3runEv),
	SYMBOL(_ZN6Thread11getPriorityEv),
	SYMBOL(_ZN6Thread7restoreEP6regs_t),
	SYMBOL(_ZN6Thread13switchThreadsEv),
	SYMBOL(_ZN10UserThread11adjustStackEP6regs_t),
	SYMBOL(_ZN6ThreadC2EPFvPvES0_PKc8RefCountI7ProcessE),

	// Queue.o
	SYMBOL(_ZN5QueueC2Ev),
	SYMBOL(_ZN5Queue6removeEP9QueueNode),
	SYMBOL(_ZN5Queue7prependEP9QueueNode),
	SYMBOL(_ZN5Queue10initializeEv),
	SYMBOL(_ZN5QueueD1Ev),
	SYMBOL(_ZN5Queue6insertEP9QueueNode),
	SYMBOL(_ZN5Queue7getHeadEv),
	SYMBOL(_ZN5QueueC1Ev),
	SYMBOL(_ZN5QueueD2Ev),
	SYMBOL(_ZN5Queue6appendEP9QueueNode),
	SYMBOL(_ZN5Queue8getCountEv),
	
	SYMBOL(_ZN5QList10removeTailEv),
	SYMBOL(_ZN5QListC2Ev),
	SYMBOL(_ZN5QList6removeEv),
	SYMBOL(_ZN5QList10removeHeadEv),
	SYMBOL(_ZN5QList7prependEPS_),
	SYMBOL(_ZN5QList4tailEv),
	SYMBOL(_ZN5QList7getNextEPS_),
	SYMBOL(_ZN5QListC1Ev),
	SYMBOL(_ZN5QList6appendEPS_),
	SYMBOL(_ZN5QList4headEv),
	SYMBOL(_ZN5QList5clearEv),
	SYMBOL(_ZN5QList7isEmptyEv),

	// Message.o
	SYMBOL(_ZN11MessagePipeD1Ev),
	SYMBOL(_ZN13MessageBuffer4readEPhj),
	SYMBOL(_ZN13MessageBufferC2Ej),
	SYMBOL(_ZN11MessagePipe5replyEPKvj),
	SYMBOL(_ZN11MessagePipe4sendEPKvjS1_jPvjS2_j),
	SYMBOL(_ZN13MessageBuffer4readEPhjS0_j),
	SYMBOL(_ZN13MessageBuffer5writeEPKhj),
	SYMBOL(_ZN11MessagePipe5replyEPKvjS1_j),
	SYMBOL(_ZN11MessagePipe4sendEPKvjPvj),
	SYMBOL(_ZN13MessageBufferD2Ev),
	SYMBOL(_ZN11MessagePipeC1Ev),
	SYMBOL(_ZN11MessagePipeD2Ev),
	SYMBOL(_ZN11MessagePipeD0Ev),
	SYMBOL(_ZN13MessageBuffer11checkBufferEj),
	SYMBOL(_ZN11MessagePipe7receiveEPvjS0_j),
	SYMBOL(_ZN11MessagePipe10invalidateEv),
	SYMBOL(_ZN13MessageBufferC1Ej),
	SYMBOL(_ZN13MessageBuffer5writeEPKhjS1_j),
	SYMBOL(_ZN11MessagePipe7isValidEv),
	SYMBOL(_ZN11MessagePipeC2Ev),
	SYMBOL(_ZN11MessagePipe7receiveEPvj),
	SYMBOL(_ZN13MessageBufferD1Ev),

	// AddressSpace.o
	SYMBOL(_ZN6RegionD2Ev),
	SYMBOL(_ZN12AddressSpace5firstEv),
	SYMBOL(_ZN12AddressSpaceC2Ev),
	SYMBOL(_ZN12AddressSpaceD1Ev),
	SYMBOL(_ZN12AddressSpace4lastEv),
	SYMBOL(_ZN6Region7getTypeEv),
	SYMBOL(_ZN12AddressSpaceC2EP9PageTableP7PageMap),
	SYMBOL(_ZN12AddressSpace6removeEP6Region),
	SYMBOL(_ZN12AddressSpaceD2Ev),
	SYMBOL(_ZN6Region7getSizeEv),
	SYMBOL(_ZN12AddressSpace11findVirtualEj),
	SYMBOL(_ZN6Region14getVirtualBaseEv),
	SYMBOL(_ZN12AddressSpaceC1EP9PageTableP7PageMap),
	SYMBOL(_ZN12AddressSpace8findTypeEj),
	SYMBOL(_ZN12AddressSpace7destroyEP6Region),
	SYMBOL(_ZN6RegionC1EP12AddressSpacejjjjj),
	SYMBOL(_ZN6Region7getNextEj),
	SYMBOL(_ZN6Region8getFlagsEv),
	SYMBOL(_ZN6RegionD1Ev),
	SYMBOL(_ZN12AddressSpace12findPhysicalEj),
	SYMBOL(_ZN12AddressSpaceC1Ev),
	SYMBOL(_ZN12AddressSpace6createEjjjjj),
	SYMBOL(_ZN12AddressSpace6insertEP6Region),
	SYMBOL(_ZN6Region15getPhysicalBaseEv),
	SYMBOL(_ZN6RegionC2EP12AddressSpacejjjjj),
};

#if 0
#define KS_DEBUG printf
#else
#define KS_DEBUG(fmt, ...) ;
#endif

#if 1
#define KS_ERROR printf
#else
#define KS_ERROR(fmt, ...) ;
#endif

int lookupExternalSymbol(char *symName, uint *adr, bool uscore) {
	unsigned i;

	if(uscore) {
		if(symName[0] != '_') {
			KS_ERROR("Name to resolve needs an underscore\n");
			return -1;
		}
		symName++;
	}

	for(i = 0; i < sizeof(syms) / sizeof(syms[0]); i++) {
		if(!strcmp(syms[i].name, symName)) {
			KS_DEBUG("Resolved reference to %s\n", symName);
			*adr = (uint) syms[i].adr;
			return 0;
		}
	}

	KS_ERROR("    Undefined external symbol '%s'\n", symName);
	return -1;
}
